package com.vecspace.scheduler;

import java.util.Date;

import org.quartz.CronScheduleBuilder;
import org.quartz.DateBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

import com.vecspace.scheduler.job.AbstractJob;
import com.vecspace.scheduler.job.JobProxy;
import com.vecspace.utils.UUIDUtil;

public class HScheduler {
	
	
	
	/**启动一个执行计划，每天执行一次，在指定的时间开始执行
	 * @param hour
	 * @param minitue 
	 * @throws SchedulerException 
	 * @author: wanghua
	 */
	public static Scheduler startExecuteJobEveryday(AbstractJob job, int hour, int minute) throws SchedulerException{		 
		Date startTime = DateBuilder.nextGivenSecondDate(null, 15);
		JobDataMap jobDataMap = new JobDataMap();
		jobDataMap.put("job_bean", job);
		String jobName = job.getJobName();
		if(jobName == null || jobName.length() == 0) {
			jobName = job.getClass().getName();
		}
		String groupName = job.getClass().getName();
		JobDetail jobDetail = JobBuilder.newJob(JobProxy.class).setJobData(jobDataMap).withIdentity(jobName, groupName).build();
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, groupName).startAt(startTime)
				.withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(hour, minute)).build();
		
		SchedulerFactory sf = new StdSchedulerFactory();
		Scheduler sched = sf.getScheduler();
		sched.scheduleJob(jobDetail, trigger);
		sched.start();
		return sched;
	}
	
	/**启动一个执行计划，每隔seconds执行一次。
	 * @param seconds
	 * @param force 如果上一次没有执行结束，是否强制触发新的执行任务
	 * @throws SchedulerException
	 * @author: wanghua
	 */
	public static Scheduler startExecuteJobInteval(AbstractJob job, int seconds, boolean force) throws SchedulerException{
		Date startTime = DateBuilder.nextGivenSecondDate(null, 5);
		JobDataMap jobDataMap = new JobDataMap();
		jobDataMap.put("job_bean", job);
		jobDataMap.put("job_excute_force", force);		
		String jobName = job.getJobName();
		if(jobName == null || jobName.length() == 0) {
			jobName = job.getClass().getName();
		}
		String groupName = job.getClass().getName() + "#" + UUIDUtil.createUUID();//多个实例不能使用想用的groupName
		JobDetail jobDetail = JobBuilder.newJob(JobProxy.class).setJobData(jobDataMap).withIdentity(jobName, groupName).build();
		SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger().withIdentity(jobName, groupName).startAt(startTime)
				.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(seconds).repeatForever()).build();
		
		SchedulerFactory sf = new StdSchedulerFactory();
		Scheduler sched = sf.getScheduler();
		sched.scheduleJob(jobDetail, trigger);
		sched.start();
		return sched;
	}
	
	
}

//Cron 触发器利用一系列特殊字符，如下所示：
//
//  反斜线（/）字符表示增量值。例如，在秒字段中“5/15”代表从第 5 秒开始，每 15 秒一次。
//
//  问号（?）字符和字母 L 字符只有在月内日期和周内日期字段中可用。问号表示这个字段不包含具体值。所以，如果指定月内日期，可以在周内日期字段中插入“?”，表示周内日期值无关紧要。字母 L 字符是 last 的缩写。放在月内日期字段中，表示安排在当月最后一天执行。在周内日期字段中，如果“L”单独存在，就等于“7”，否则代表当月内周内日期的最后一个实例。所以“0L”表示安排在当月的最后一个星期日执行。
//
//  在月内日期字段中的字母（W）字符把执行安排在最靠近指定值的工作日。把“1W”放在月内日期字段中，表示把执行安排在当月的第一个工作日内。
//
//  井号（#）字符为给定月份指定具体的工作日实例。把“MON#2”放在周内日期字段中，表示把任务安排在当月的第二个星期一。
//
//  星号（*）字符是通配字符，表示该字段可以接受任何可能的值。
//
//字段 允许值 允许的特殊字符
//秒 0-59 , - * /
//分 0-59 , - * /
//小时 0-23 , - * /
//日期 1-31 , - * ? / L W C
//月份 1-12 或者 JAN-DEC , - * /
//星期 1-7 或者 SUN-SAT , - * ? / L C #
//年（可选） 留空, 1970-2099 , - * /
//
//表达式意义
//"0 0 12 * * ?" 每天中午12点触发
//"0 15 10 ? * *" 每天上午10:15触发
//"0 15 10 * * ?" 每天上午10:15触发
//"0 15 10 * * ? *" 每天上午10:15触发
//"0 15 10 * * ? 2005" 2005年的每天上午10:15触发
//"0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发
//"0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发
//"0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
//"0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发
//"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发
//"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发
//"0 15 10 15 * ?" 每月15日上午10:15触发
//"0 15 10 L * ?" 每月最后一日的上午10:15触发
//"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发
//"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发
//"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发
//每天早上6点
//
//0 6 * * *
//
//每两个小时
//
//0 */2 * * *
//晚上11点到早上8点之间每两个小时，早上八点
//
//0 23-7/2，8 * * *
//
//每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
//
//0 11 4 * 1-3
//1月1日早上4点
//
//0 4 1 1 *